package oauth.service.finger;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.springframework.stereotype.Service;

import com.sun.jna.Library;
import com.sun.jna.Native;
import sun.misc.BASE64Decoder;

/**
 * @author Pan JinWen
 * @time 2016年5月21日下午5:15:28
 */
@Service
public class FingerDll {
	private static BASE64Decoder decoder = new BASE64Decoder();
	private static String one = "QwErEgFjPwAAAAAAAAAAAAAAAC4BmoCKAP///////8cch/xHIdv8aSfT/JkplvwwLez8IjdF/GVBFvyiRI38l06b/MFadfxvWxH8M19U/BNjafyXYZj8i2k//txqVvygfYf8s4Nw/OSGS/w4ilv80JJU/EybUvxDoRn+OKNo/GGwXfyPsWD8G7Nw/Iq3aPzMtUb838M4/H/GYP6Q2KL8r9k0/NTmKfyY9hT82foW/GEJiv2TEw/9HyA7/2MiUP9VJkb/wCS8/ZcnB/2hN7H9XUZN/45XrP0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFU=";
	private static String two = "QwErEgFjPgAAAAAAAAAAAAAAADEBmnZgAP///////8ATi/yNF6P8ORvX/FUg0/wbJvb8ZS3K/JUum/xULxb8aDQL/IY1p/wTO0z8YUEL/IJBqvy5QX38fUpI/ntSuvwgVk/8kliU/NdZU/wIZhH+d2Y1/qNlcvzdc0X8c3YZ/iJ9Wvy/fUn8TIFd/ECJZfwzjin+JJhr/L6cOPx5nSL80qgt/KG3MfzExh/8hdIR/MzYEfxa7ZH8hfEP/LYCv/1RA1H/iAoI/UENSv8NEkH/mRa6/VcyVP+JPLH9hUwG/W1WV/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIY=";
	private static float[] MatchScore = new float[1];
	private static int[] Score = new int[1];
	// 安全等级1~5 1基数10分 5基数为50分
	private static byte secLevel = 5;

	// private static String one =
	// "030153230000e006c002c002c002c002800280028002800280028002800280028002c002c002c002000000000000000000000000000000003914ec3e681558fe661b83de2c1ed27e3123115e4fa313fe69b84dde6809185f428facdf4d1495ff4f1a54ff2a2b8ebf33adcdff29b78c9f45ba885f4dbfc49f5b41e97f4d84159c4c87c09c4da8d29d3a374a9d14334dba1033e63a542ac37b3436cbdb59ba2013583d00d92cbdcb3959360a965f3b9a305c2e58b7353c89b7313ccab7623c53b5572fd21000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
	// private static String two =
	// "030160150000c1fe80fe80fe807e807e803e803e803e803e803e803e803e807e807e807e80fe80fe000000000000000000000000000000002406597e1b87d81e198dc2be418e061e3b935b9e2b1399be311dda9e121fc25e142c57be28af84bf12335857144258371e9517dc1c18829c38281b5c3127597d133c049316a45878162682b21a27593217be1bd200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000011f00000000000000000000cb0000000000000000210000d100000000000000000000009c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";

	static {
	}

	public static void main(String[] args) throws IOException {
		FingerDll fingerDll = new FingerDll();
		// System.out.println(System.getProperty("java.library.path"));
		// System.out.println(System.getProperty("file.encoding"));
		// System.setProperty("jna.encoding", "GB2312");
		fingerDll.fingerBegin();
		int fingermatch = fingerDll.fingermatch(one, two, MatchScore);
		System.out.println(fingermatch + ":" + MatchScore[0]);

		// int fingermatch = fingerDll.fingermatch(one, two, secLevel,
		// MatchScore);
		// System.out.println(fingermatch + "," + MatchScore[0]);
	}

	public void fingerBegin() {
		// System.out.println("LIVESCAN_Init:"+FingerLibrary.dll1.LIVESCAN_Init());
		// System.out.println("FP_Begin:" + FingerLibrary.dll2.FP_Begin());
		System.err.println("init:" + FingerLibrary.dll1.LIVESCAN_Init());
		System.err.println("begin:" + FingerLibrary.dll2.FP_Begin());
		return;
	}

	public int fingermatch(String src, String dst, float[] matchScore) throws IOException {
		// return FingerLibrary.dll.Match2Fp(HexString2Bytes(src),
		// HexString2Bytes(dst));
		// return FingerLibrary.dll.UserMatch(HexString2Bytes(src),
		// HexString2Bytes(dst), SecLevel, MatchScore);
		return FingerLibrary.dll2.FP_FeatureMatch(decoder.decodeBuffer(src), decoder.decodeBuffer(dst), matchScore);
	}

	public interface FingerLibrary extends Library {
		// 加载链接库
		FingerLibrary dll = (FingerLibrary) Native.loadLibrary("ARTH_DLL", FingerLibrary.class);

		int Match2Fp(byte[] src, byte[] dst);
		// int WINAPI Match2Fp(unsigned char* Src,unsigned char* Dst);

		// 64位DLL
		// FingerLibrary dll0 = (FingerLibrary) Native.loadLibrary("ARTH_LIB",
		// FingerLibrary.class);

		public int fingermatch(String src, String dst, byte SecLevel, int[] MatchScore);
		// int UserMatch(unsigned char *Src,unsigned char *Dst,unsigned char
		// SecuLevel,int *MatchScore)

		FingerLibrary dll1 = (FingerLibrary) Native.loadLibrary("ID_FprCap", FingerLibrary.class);

		int FP_Begin();
		// int __stdcall FP_Begin();

		int LIVESCAN_Init();
		// int __stdcall LIVESCAN_Init()

		FingerLibrary dll2 = (FingerLibrary) Native.loadLibrary("ID_Fpr", FingerLibrary.class);

		int FP_FeatureMatch(byte[] src, byte[] dst, float[] matchScore);
		// int __stdcall FP_FeatureMatch(unsigned char * pFeatureData1, unsigned
		// char * pFeatureData2, float * pfSimilarity);
	}

	private static String hexString = "0123456789ABCDEF";

	/**
	 * 将字符串编码成16进制数字,适用于所有字符（包括中文）
	 */
	public static String encode(String str) {
		// 根据默认编码获取字节数组
		byte[] bytes = str.getBytes();
		StringBuilder sb = new StringBuilder(bytes.length * 2);
		// 将字节数组中每个字节拆解成2位16进制整数
		for (int i = 0; i < bytes.length; i++) {
			sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));
			sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0));
		}
		return sb.toString();
	}

	/**
	 * 将16进制数字解码成字符串,适用于所有字符（包括中文）
	 */
	public static String decode(String bytes) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);
		// 将每2位16进制整数组装成一个字节
		for (int i = 0; i < bytes.length(); i += 2)
			baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes.charAt(i + 1))));
		return new String(baos.toByteArray());
	}

	/**
	 * 将指定字符串src，以每两个字符分割转换为16进制形式 如："2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF,
	 * 0xD9}
	 * 
	 * @param src
	 *            String
	 * @return byte[]
	 */

	public static byte[] HexString2Bytes(String src) {
		byte[] tmp = src.getBytes();
		byte[] ret = new byte[src.length() / 2];
		for (int i = 0; i < ret.length; i++) {
			ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
		}

		return ret;
	}

	/**
	 * 将两个ASCII字符合成一个字节； 如："EF"--> 0xEF
	 * 
	 * @param src0
	 *            byte
	 * @param src1
	 *            byte
	 * @return byte
	 */
	public static byte uniteBytes(byte src0, byte src1) {
		byte _b0 = (byte) (Byte.decode("0x" + new String(new byte[] { src0 })).byteValue() << 4);
		byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 })).byteValue();
		return (byte) (_b0 ^ _b1);
	}

}
